#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <unistd.h>
#include <malloc.h>
#include <termios.h>
#include <strings.h>
#include <stdarg.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <time.h> 

#include <linux/watchdog.h>

#include "libtcu.h"
#include "gpio.h"


#define STX		0x02
#define ETX		0x03
#define MAX_PACKET_SIZE 1024

//#define DEbug

char *gps_config = "/etc/tcu/gps.ini";
static unsigned char watchdog_fd;
static unsigned char esam_fd;

#if 0
void set_speed(int fd, int speed);
int set_Parity(int fd,int databits,int stopbits,int parity);
static int setio(char gpionum,char value);
static int getio(char gpionum);
static int getiovalue(char gpionum);
int InitBDGPS(int *bdgps_fd);
int GetBDGPSState(int bdgps_fd,int *bdgps_state);
int GetBDGPSData(int bdgps_fd,char *bdgps_loca_state,char *bdgps_we,unsigned int *bdgps_Longitude,char *bdgps_ns,unsigned int *bdgps_Latitude,
                unsigned int *bdgps_Altitude, unsigned int *bdgps_Time);
int EnableWtd(int TimeOut);
#endif

static int setio(char gpionum ,char value)
{
	struct gpiodev *dev;

	dev = gpiodev_construct(gpionum);
	if (NULL == dev) {
		printf("gpio_construct error\n");
		return -1;
	}
	if (gpiodev_export(dev) < 0) {
		printf("gpiodev_export error\n");
		gpiodev_deconstruct(dev);
		return -1;
	}
	gpiodev_setdir(dev, 0);
	gpiodev_setval(dev, value);
	return 0;
}

static int getio(char gpionum)
{
	struct gpiodev *dev;
	dev = gpiodev_construct(gpionum);
	if (NULL == dev) {
		printf("gpio_construct error\n");
		return -1;
	}
	if (gpiodev_export(dev) < 0) {
		printf("gpiodev_export error\n");
		gpiodev_deconstruct(dev);
		return -1;
	}

	gpiodev_setdir(dev, 1);
	return gpiodev_getval(dev);
}

static int getiovalue(char gpionum)
{
	struct gpiodev *dev;
	dev = gpiodev_construct(gpionum);
	if (NULL == dev) {
		printf("gpio_construct error\n");
		return -1;
	}
	if (gpiodev_export(dev) < 0) {
		printf("gpiodev_export error\n");
		gpiodev_deconstruct(dev);
		return -1;
	}

	//        gpiodev_setdir(dev, 0);
	return gpiodev_getval(dev);
}

static int uart_send(unsigned char *date, unsigned int len)
{
	unsigned char txbuff[1024];
	unsigned char ecc=0,i;
	memcpy(txbuff+3, date, len);

	txbuff[0] = STX;
	txbuff[1] = ((len >> 8) & 0xFF);
	txbuff[2] = ((len >> 0) & 0xFF);
	ecc = txbuff[3];
	for ( i = 4; i < len + 3; i++)
		ecc ^= txbuff[i];
	txbuff[5 + len - 2]   = ecc;
	txbuff[5 + len - 1]   = ETX;
#ifdef DEbug
	for(i = 0; i < (len + 5); i++)
	printf("am335x->stm32 senddate[%d] %02x\n", i, *(txbuff + i));
#endif
	write(esam_fd, txbuff, len + 5);
	return 0;

}

int set_serial_opt(int serial_fd, int btd, char O, int stop, int num_bit)
{
	struct termios newterm;
	if(tcgetattr(serial_fd, &newterm)  !=  0)
	{
		perror("tcgetattr");
		return -1;
	}

	bzero(&newterm,sizeof(newterm));
	newterm.c_cflag  |=  CLOCAL | CREAD;
	newterm.c_cflag &= ~CSIZE;

	switch(btd)
	{
		case 1:
			cfsetispeed(&newterm, B2400);
			cfsetospeed(&newterm, B2400);
			break;
		case 2:
			cfsetispeed(&newterm, B38400);
			cfsetospeed(&newterm, B38400);
			break;
		case 3:
			cfsetispeed(&newterm, B9600);
			cfsetospeed(&newterm, B9600);
			break;
		case 4:
			cfsetispeed(&newterm, B115200);
			cfsetospeed(&newterm, B115200);
			break;
		default:
			cfsetispeed(&newterm, B115200);
			cfsetospeed(&newterm, B115200);
			break;

	}
	switch(O)
	{
		case 'e':
			newterm.c_cflag |= (PARODD | PARENB);
			newterm.c_iflag |= INPCK;
			break;
		case 'o':
			newterm.c_cflag |= PARENB;
			newterm.c_cflag &= ~PARODD;
			newterm.c_iflag |= INPCK;
			break;
		case 'w':
			newterm.c_cflag &= ~PARENB;
			break;
	}
	switch(stop)
	{
		case 1:
			newterm.c_cflag &=  ~CSTOPB;
			break;
		case 2:
			newterm.c_cflag |=  CSTOPB;
			break;
	}

	switch(num_bit)
	{
		case 7:
			newterm.c_cflag |= CS7;
			break;
		case 8:
			newterm.c_cflag |= CS8;
			break;
	}

	newterm.c_cc[VTIME]  = 10;
	newterm.c_cc[VMIN] = 0;

	tcflush(serial_fd,TCIFLUSH);
	tcsetattr(serial_fd,TCSANOW,&newterm);
	return 0;
}

//*-----------------------------------------------------------

//*

//**   ESAM设备相关部分

//*

//*-----------------------------------------------------------

//*------------------------------------------------------------------------------------------------

//* 函数名称:  InitEsam

//* 功能描述:  ESAM初始化

//* 入口参数:  无

//* 返回值  :  

//*                成功，返回:ERROR_OK(==0)；

//*                失败，返回(ERROR_FAIL)

//* 备注    :  无

//*------------------------------------------------------------------------------------------------
int InitEsam()
{
#ifdef DEbug
	printf("@@@@@@@@@@@@@	ESAM	@@@@@@@@@@@@@@ init        \n");
#endif
	esam_fd = open("/dev/ttyS9", O_RDWR | O_NOCTTY | O_NDELAY);

	if(set_serial_opt(esam_fd, 3, 'n', 1, 8) == 0)
		printf("set serial port ok\n");

	fcntl(esam_fd, F_SETFL, O_NONBLOCK);
	return ERROR_OK;
}
//*------------------------------------------------------------------------------------------------

//* 函数名称:  ResetEsam

//* 功能描述:  ESAM复位操作

//* 入口参数:

//*           -- Rstcmd:  - 0  冷复位， 1  热复位

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :  无

//*------------------------------------------------------------------------------------------------

int ResetEsam(int Rstcmd)
{
	unsigned char i,res;
	unsigned  char esam_reset_date[2] = {0x10, 0x01};
#ifdef DEbug
	printf("@@@@@@@@@@@@@	ESAM	@@@@@@@@@@@@@@@@@@@@@@@@@@@ResetEsam %d\r\n", Rstcmd);
#endif
	if(uart_send(esam_reset_date, 2))
		return ERROR_FAIL;

	return ERROR_OK;
}
//*------------------------------------------------------------------------------------------------

//* 函数名称:  ReadEsam

//* 功能描述:  读ESAM数据

//* 入口参数:

//*           -- buffer:     - 读取的数据存放缓冲区

//*           -- uWntLen:    - 此次希望得到报文长度

//*           -- pGetlen:    - 返回实际读取的报文长度

//*           -- timesoutus: - 最大的阻塞读取等待间隔，单位: useconds(微秒)

//*                            若timesoutus=0，非阻塞读模式.

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_INPARA/ERROR_TIMEOUT/ERROR_SYS/ERROR_NOSUPPORT/ERROR_FAIL)

//* 备注    :  

//*------------------------------------------------------------------------------------------------

int ReadEsam(unsigned char *buffer, unsigned int uWntLen, unsigned int *pGetlen, unsigned int timesoutus)
{
#ifdef DEbug
	printf("@@@@@@@@@@@@@	ESAM	@@@@@@@@@@@@@@ read      len=%d  timesout us=%d\n", uWntLen, timesoutus);
#endif
        fd_set fds;
        struct timeval tv;
        int ret;
	unsigned char ecc = 0, i, dl = 0;
	unsigned int rlen = uWntLen + 5;
	unsigned char rxbuf[rlen];
	unsigned char rxbufflen;
        *pGetlen = 0;

        FD_ZERO(&fds);
        FD_SET(esam_fd, &fds);

	memset(rxbuf, 0, rlen);
readdata:
        tv.tv_sec = 1;
        tv.tv_usec = timesoutus+500000;
        ret = select(esam_fd+1, &fds, NULL, NULL, &tv);
        switch(ret) {
        case -1:
        	printf("-1 %s %s %d\n", __FILE__, __func__, __LINE__);
        	ret = -1;
		goto out;
        case 0:
		if ((*pGetlen) > 0)
			goto readend;
        	printf("0 %s %s %d\n", __FILE__, __func__, __LINE__);
        	ret = -1;
		goto out;
        default:
        	break;
	}

        rxbufflen = read(esam_fd, &rxbuf[(*pGetlen)], rlen);
//        printf("*pGetlen=%d\n",(*pGetlen));
//	printf("rxbufflen = %d\n", rxbufflen);
	if (rxbufflen > 0) {
//        	for(i = 0+*pGetlen;  i < rxbufflen + *pGetlen ; i++)
  //      		printf("stm32->am335x[%d]=%02x\n", i, rxbuf[i]);
		rlen -= rxbufflen;
		*pGetlen += rxbufflen;
	} else {
        	ret = -1;
		goto out;
	}
	if (rlen > 0)
		goto readdata;	

	readend:
	rlen = *pGetlen;//rxbufflen;

        printf("len=%d,rxbuflen=%d\n",rlen,rxbufflen);

#ifdef DEbug	
        for(i = 0;  i < rlen ; i++)
        	printf("*  stm32->am335x[%d]=%02x\n", i, rxbuf[i]);
#endif
        if((rxbuf[0]!=0x02)||(rxbuf[rlen-1]!=0x03))
        {
		printf("rxbuf[0] = %02x \n rxbuf[rlen-1] = %02x \n rlen = %02x \n",rxbuf[0],rxbuf[rlen-1],rlen);
                printf("ESAM STX OR ETX ERROR \n");
                ret = -1;
		goto out;
        }
        dl=(rxbuf[1]<<8)+rxbuf[2];
        for( i = 0; i < dl; i++)
                ecc ^= rxbuf[3+i];
        if (ecc != rxbuf[3+dl])
        {
                printf("ecc error.  ecc=%x   rxbuff[3+%d]=%x\n",ecc,dl,rxbuf[3+dl]);
                ret = -1;
		goto out;
        }
	ret = 0;	
out:
	(*pGetlen) = (*pGetlen) - 5;
	memcpy(buffer, &rxbuf[3], *pGetlen);
	return ret;	

}




//*------------------------------------------------------------------------------------------------

//* 函数名称:  WriteEsam

//* 功能描述:  向ESAM写数据

//* 入口参数:

//*           -- buffer:     - 写入的数据存放缓冲区

//*           -- len:        - 写入的数据长度(指针)

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_INPARA/ERROR_TIMEOUT/ERROR_SYS/ERROR_NOSUPPORT/ERROR_FAIL)

//* 备注    :  

//*            

//*------------------------------------------------------------------------------------------------

int WriteEsam(unsigned char *buffer, unsigned int len)
{
#ifdef DEbug
	printf("@@@@@@@@@@@@@	ESAM	@@@@@@@@@@@@@@ write      len=%d  \n",len);
#endif
	if(uart_send(buffer,len)<0)
		return ERROR_FAIL;
	return ERROR_OK;
}
//*------------------------------------------------------------------------------------------------

//* 函数名称:  EsamStop

//* 功能描述:  停活

//* 入口参数:

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :  无

//*------------------------------------------------------------------------------------------------
int StopEsam()
{

	unsigned  char esam_reset_date[2]={0x10,0x02};
#ifdef DEbug
	printf("@@@@@@@@@@@@@	ESAM	@@@@@@@@@@@@@@ stop      len=%d  \n");
#endif
	if(uart_send(esam_reset_date,2))
		return ERROR_FAIL;

	return ERROR_OK;
}
//************************************************************

//*-----------------------------------------------------------

//*

//**   PSAM设备相关部分

//*

//*-----------------------------------------------------------

//************************************************************
#if 0
//*------------------------------------------------------------------------------------------------

//* 函数名称:  InitPsam

//* 功能描述:  PSAM初始化

//* 入口参数:  无

//*

//* 返回值  :  

//*                成功，返回:ERROR_OK(==0)；

//*                失败，返回(ERROR_FAIL)

//* 备注    :  无

//*------------------------------------------------------------------------------------------------

int InitPsam()
{
	return ERROR_OK;
}



//*------------------------------------------------------------------------------------------------

//* 函数名称:  ResetPsam

//* 功能描述:  PSAM复位操作

//* 入口参数:

//*           -- Rstcmd:    - 0  冷复位， 1  热复位

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :  无

//*------------------------------------------------------------------------------------------------

int ResetPsam(int Rstcmd)
{
	return ERROR_OK;
}





//*------------------------------------------------------------------------------------------------

//* 函数名称:  ReadPsam

//* 功能描述:  读PSAM数据

//* 入口参数:

//*           -- buffer:     - 读取的数据存放缓冲区

//*           -- uWntLen:    - 此次希望得到报文长度

//*           -- pGetlen:    - 返回实际读取的报文长度

//*           -- timesoutus: - 最大的阻塞读取等待间隔，单位: useconds(微秒)

//*                            若timesoutus=0，非阻塞读模式.

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_INPARA/ERROR_TIMEOUT/ERROR_SYS/ERROR_NOSUPPORT/ERROR_FAIL)

//* 备注    :  

//*------------------------------------------------------------------------------------------------

int ReadPsam(unsigned char *buffer, unsigned int uWntLen, unsigned int *pGetlen, unsigned int timesoutus)
{
	return ERROR_OK;
}







//*------------------------------------------------------------------------------------------------

//* 函数名称:  WritePsam

//* 功能描述:  向PSAM写数据

//* 入口参数:

//*           -- buffer:     - 写入的数据存放缓冲区

//*           -- len:        - 写入的数据长度

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_INPARA/ERROR_TIMEOUT/ERROR_SYS/ERROR_NOSUPPORT/ERROR_FAIL)
value

//* 备注    :  

//*            

//*------------------------------------------------------------------------------------------------

int WritePsam(unsigned char *buffer, unsigned int len)
{
	return ERROR_OK;
}





//*------------------------------------------------------------------------------------------------

//* 函数名称:  StopPsam

//* 功能描述:  停活

//* 入口参数:

//*            --psam_fd:    -为PSAM文件描述符

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :  无

//*------------------------------------------------------------------------------------------------

int StopPsam()
{
	return ERROR_OK;
}

y



#endif

//************************************************************

//*-----------------------------------------------------------

//*

//**   IO设备相关部分

//*

//*-----------------------------------------------------------

//************************************************************


//*--------------------------------------------------------------------------

//* 函数名称:  InitExIOState

//* 功能描述:  初始化GPIO状态

//* 入口参数:  无

//*

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :   无

//*--------------------------------------------------------------------------

int InitExIOState()
{
/* 这里反了 0状态对应继电器闭合 1状态对应继电器打开 */
	setio(48, 1);
	setio(49, 1);
	setio(50, 1);
	setio(51, 1);
	setio(52, 1);
	setio(53, 1);
	getio(22);
	getio(23);
	getio(26);
	getio(27);
	getio(46);
	getio(47);
	return ERROR_OK;
}

//* 函数名称:  SetExIOOutState

//* 功能描述:  设置GPIO为电平输出，并设置IO的输出状态

//* 入口参数:

//*           -- gpio:    - IO端口号

//*           -- state:   - IO输出状态(0:打开/1:闭合)

//*

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :   无

//*--------------------------------------------------------------------------

int SetExIOOutState(int gpio, int state)
{
#ifdef DEbug
	printf("@@@@@@@@@@@@@	SETIO	@@@@@@@@@@@@@@ gpio=%d state=%d\n",gpio,state);
#endif
	if((state != 0) && (state != 1))
	{
		return ERROR_INPARA;
	}
	if((gpio < 0)||(gpio > 5))
		return ERROR_FAIL;
	switch(gpio) {
	case 0:
		if(setio(48,(1-state)) < 0)
			return ERROR_SYS;
		else
			return ERROR_OK;
	case 1:
		if(setio(49,(1-state)) < 0)
			return ERROR_SYS;
		else
			return ERROR_OK;
	case 2:
		if(setio(50,(1-state)) < 0)
			return ERROR_SYS;
		else
			return ERROR_OK;
	case 3:
		if(setio(51,(1-state)) < 0)
			return ERROR_SYS;
		else
			return ERROR_OK;
	case 4:
		if(setio(52,(1-state)) < 0)
			return ERROR_SYS;
		else
			return ERROR_OK;
	case 5:
		if(setio(53,(1-state)) < 0)
			return ERROR_SYS;
		else
			return ERROR_OK;
	default :return ERROR_FAIL;

	}
}


//*--------------------------------------------------------------------------

//* 函数名称:  GetExIOOutState

//* 功能描述:  读取为电平输出类型IO的当前输出状态

//* 入口参数:

//*           -- gpio:     - IO端口号

//*           -- curstate: - 返回IO的当前输出状态(0:打开/1:闭合)

//*

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :   无

//*--------------------------------------------------------------------------

int GetExIOOutState(int gpio,int *curstate)
{
#ifdef DEbug
	printf("@@@@@@@@@@@@@	GETIO	@@@@@@@@@@@@@@ gpio=%d curstate=%d\n", gpio, *curstate);
#endif
	if((gpio < 0)||(gpio > 5))
                return ERROR_FAIL;
        switch(gpio) {
        case 0:*curstate=1-getiovalue(48);break;
        case 1:*curstate=1-getiovalue(49);break;
        case 2:*curstate=1-getiovalue(50);break;
        case 3:*curstate=1-getiovalue(51);break;
        case 4:*curstate=1-getiovalue(52);break;
        case 5:*curstate=1-getiovalue(53);break;
	}
	return ERROR_OK;
}

//*------------------------------------------------------------------------------------------------

//* 函数名称:  GetExIOInValue

//* 功能描述:  读取为电平输入类型IO的当前输入值

//* 入口参数:

//*           -- gpio:     - IO端口号

//*           -- curval:   - 返回IO的当前输入状态(0:低电平/1:高电平)

//*

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_INPARA/ERROR_TIMEOUT/ERROR_SYS/ERROR_NOSUPPORT/ERROR_FAIL)

//* 备注    :   无

//*------------------------------------------------------------------------------------------------

int GetExIOInValue(int gpio,int *curval)
{
#ifdef DEbug
	printf("@@@@@@@@@@@@@	GETIOin	@@@@@@@@@@@@@@ gpio=%d curval=%d\n", gpio, *curval);
#endif
	if((gpio < 0)||(gpio > 5))
                return ERROR_FAIL;
        switch(gpio) {
        case 0:*curval=getiovalue(22);break;
        case 1:*curval=getiovalue(23);break;
        case 2:*curval=getiovalue(26);break;
        case 3:*curval=getiovalue(27);break;
        case 4:*curval=getiovalue(46);break;
        case 5:*curval=getiovalue(47);break;
	default: return ERROR_FAIL;
	}

	return ERROR_OK;
}

//************************************************************

//*-----------------------------------------------------------

//*

//**   通信设备相关部分

//*

//*-----------------------------------------------------------

//************************************************************


//*--------------------------------------------------------------------------

//* 函数名称:  GetMobileSignal

//* 功能描述:  获取当前信号强度

//* 入口参数:

//*           无

//*

//* 返回值  :  当前信号强度

//* 备注    :   

//*--------------------------------------------------------------------------

int GetMobileSignal()
{
	int serial_fd, len, i, singel, singel1;
        char read_buf[100] = {0};
        char *ret=NULL;
        char write_buf[7] = { 0x41, 0x54, 0x2b, 0x43, 0x53, 0x51, 0x0d };//"AT+CSQ\n"
        serial_fd = open("/dev/ttyUSB5" ,O_RDWR | O_NOCTTY | O_NDELAY );
        if(serial_fd < 0)
                printf("4g singel open error\n");
        while(1) {
                tryagain :
                memset(read_buf, 0, sizeof(read_buf));
                write(serial_fd, write_buf, 7);
                len = read(serial_fd, read_buf, sizeof(read_buf));
                if( len == 12 ) {
#ifdef DEbug
                printf("%s\n len = %d\n", read_buf, len);
#endif
                if ((ret=strstr(read_buf, "+CSQ")) != NULL) {
#ifdef DEbug
                        for(i = 0; i < len; i++)
                        {
                                printf("read_buf[%d] = %02x  \n", i, read_buf[i]);
                        }
#endif
                        sscanf(ret,"+CSQ: %d,%d", &singel, &singel1);
                        printf("singel1 strength = %d\n",singel1);
                        printf("singel strength = %d\n",singel);
                } else {
                        printf("no useful AT message, restart\n");
                        goto tryagain;
                }
		close(serial_fd);
                return singel;
                }
        }
}

//*--------------------------------------------------------------------------

//* 函数名称:  ChangeSimChan

//* 功能描述:  切换SIM卡的通道

//* 入口参数:

//*           -- chan:   - SIM卡通道 (0:sim0 / 1:sim1)

//*

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :   默认sim0是主卡

//*--------------------------------------------------------------------------

int ChangeSimChan(int chan)
{
#ifdef DEbug
	printf("@@@@@@@@@@@@@	ChangeSimChan	@@@@@@@@@@@@@@ chan=%d\n", chan);
#endif
	switch (chan)
	{
		case 0:
			system("killall -9 4g.sh");
			system("pkill -9 pppd");
			sleep(1);
			setio(57, 0);
			setio(65, 0);
			setio(65, 1);
			sleep(10);
			system("/etc/4g.sh &");
			break;
		case 1:
			system("killall -9 4g.sh");
			system("pkill -9 pppd");
			sleep(1);
			setio(57, 1);
			setio(65, 0);
			setio(65, 1);
			sleep(10);
			system("/etc/4g.sh &");
			break;
		default:
			return ERROR_INPARA;
	}
	return ERROR_OK;
}



//*--------------------------------------------------------------------------

//* 函数名称:  GetCurSimChan

//* 功能描述:  获取当前所用SIM卡编号

//* 入口参数:

//*           -- chan:   - 当前SIM卡通道 (0:sim0 / 1:sim1)

//*

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :   无

//*--------------------------------------------------------------------------

int GetCurSimChan(int *chan)
{
#ifdef DEbug
	printf("@@@@@@@@@@@@@	GetCurSimChan	@@@@@@@@@@@@@@ \n");
#endif
	*chan=getiovalue(57);

	return ERROR_OK;
}

//************************************************************

//*-----------------------------------------------------------

//*

//**   北斗/GSP相关部分

//*

//*-----------------------------------------------------------

//************************************************************


//从INI文件读取字符串类型数据  
char *GetIniKeyString(char *title,char *key, char *filename)
{
    FILE *fp;
    char szLine[1024];
    static char tmpstr[1024];
    int rtnval;
    int i = 0;
    int flag = 0;
    char *tmp;

    if((fp = fopen(filename, "r")) == NULL)
    {
        printf("have   no   such   file \n");
        return "";
    }
while(!feof(fp)) {

        rtnval = fgetc(fp);
        if(rtnval == EOF)
        {
            break;
        }
        else
        {
            szLine[i++] = rtnval;
        }
        if(rtnval == '\n')

      {
            szLine[--i] = '\0';
            i = 0;
            tmp = strchr(szLine, '=');

            if(( tmp != NULL )&&(flag == 1))
            {
                if(strstr(szLine,key)!=NULL)
                {
                    //注释行  
                    if ('#' == szLine[0])
                    {
                    }
                    else if ( '/' == szLine[0] && '/' == szLine[1] )
                    {

                    }
                    else
                    {
                        //找打key对应变量  
                        strcpy(tmpstr,tmp+1);
                        fclose(fp);
                        return tmpstr;
                    }
                }
            }
            else
            {
                strcpy(tmpstr,"[");
                strcat(tmpstr,title);
                strcat(tmpstr,"]");
                if( strncmp(tmpstr,szLine,strlen(tmpstr)) == 0 )
                {
                    //找到title  
                    flag = 1;
                }
            }
        }
    }
    fclose(fp);
    return "";
}

int GetIniKeyInt(char *title,char *key,char *filename)
{
    return atoi(GetIniKeyString(title,key,filename));
}


//*--------------------------------------------------------------------------

//* 函数名称:  InitBDGPS

//* 功能描述:  初始化北斗/GPS模块

//* 入口参数:

//*           -- bdgps_fd   北斗/GPS设备文件描述符

//*

//* 返回值  :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注    :   

//*--------------------------------------------------------------------------
static void setTermios(struct termios * pNewtio, int uBaudRate)
{
	 bzero(pNewtio, sizeof(struct termios)); /* clear struct for new port settings */
        //8N1  
        pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;
        pNewtio->c_iflag = IGNPAR;
        pNewtio->c_oflag = 0;
        pNewtio->c_lflag = 0; //non ICANON  
}

static void um220_uart_init(int ttyFd,struct termios *oldtio,struct termios *newtio)
{
	tcgetattr(ttyFd, oldtio); /* save current serial port settings */
	setTermios(newtio, B9600);
	tcflush(ttyFd, TCIFLUSH);
	tcsetattr(ttyFd, TCSANOW, newtio);
}

int InitBDGPS(int *bdgps_fd)
{
        char newbuf[MAX_PACKET_SIZE];
	int um220_fd ;
        char msg[20], *ret = NULL;
        struct termios oldtio, newtio;
	
#ifdef DEbug
	printf("@@@@@@@@@@@@@@@@@@@@@@@@ InitBDGPS \n");
#endif
        if ((um220_fd = open("/dev/ttyS1", O_RDWR)) < 0) {
            printf("error: Can't open serial port /dev/ttyS1 !\n");
                    return -1;
	}
        um220_uart_init(um220_fd, &oldtio, &newtio);
#if 0
        memset(msg, 0, sizeof(msg));
        strcpy(msg, "$cfgsys,h11");
        if(write(um220_fd, msg, sizeof(msg)) < 0) {
                printf("Failed to set BD+GPS modules!\n");
		return -1;
	}
	printf("open ttyS1 ok\n", um220_fd);
#endif
	*bdgps_fd = um220_fd;

	if(access(gps_config,F_OK)<0) {
                printf("\n\t** FAIL: %s  not exist! **\n\n",gps_config);
        } else {
                printf("\n\t** read  %s  **\n",gps_config);
		#define GPSCONFIG
        }

	return 0;
}

//*--------------------------------------------------------------------------

//* 函数名称:  GetBDGPSState

//* 功能描述:  获取当前北斗/GPS的状态

//* 入口参数:

//*           -- bdgps_fd       - 北斗/GPS设备文件描述符

//*           -- bdgps_state    - 当前北斗或者GPS的定位状态:返回：0-无效定位或未定位成功，1-SPS模式定位有效,2-DGPS模式定位有效，其他值无效。

//* 返回值    :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注         :   

//*--------------------------------------------------------------------------

int GetBDGPSState(int bdgps_fd,int * bdgps_state)
	
{
	char newbuf[MAX_PACKET_SIZE];
	int nb;
	char *ret = NULL;
	int nQ, nN, nB, nC;			//GPS状态,卫星数量,
        char cX, cY, cM1, cM2;			//纬度方向,经度方向,
        float fTime, fX, fY, fP, fH, fB, fD;	//timeUTC时间,纬度,经度,精度百分比,海拔高,大地水准面高度,差分GPS数据期限

	 unsigned int c;
        c = GetIniKeyInt("GPS_CONFIG","ENABLE",gps_config);
        if(c==1)
        {
        *bdgps_state = 1;
	return 0;
	}

while (1) {
	memset(newbuf, 0, 1024);
        nb = read(bdgps_fd, newbuf, MAX_PACKET_SIZE);
	if (nb == -1) {
            perror("read uart error");
            return -1;
        }
        if ((ret = strstr(newbuf, "$GNGGA")) != NULL) {
//	strcpy(ret,"$GNGGA,000000.000,0000.000000,N,00000.000000,E,8,00,127.000,0.000,M,0,M,,*69");
	sscanf(ret,"$GNGGA,%f,%f,%c,%f,%c,%d,%02d,%f,%f,%c,%f,%c,%f,%04d%02x",&fTime,&fX,&cX,&fY,&cY,&nQ,&nN,&fP,&fH,&cM1,&fB,&cM2, &fD, &nB, &nC);
	*bdgps_state = nQ;
	return 0;
        }
	else {
		usleep(200000);
	}
		
    }
	
}

//*--------------------------------------------------------------------------

//* 函数名称:  GetBDGPSData

//* 功能描述:  获取北斗/GPS当前定位和时间相关数据

//* 入口参数:

//*           -- bdgps_fd          - 北斗/GPS设备文件描述符

//*           -- bdgps_loca_state  - 当前北斗或者GPS的定位状态:返回：0-无效定位或未定位成功，1-SPS模式定位有效,2-DGPS模式定位有效，其他值无效。

//*           -- bdgps_we          - 西经东经。返回：'W'(87)-西经，'E'(69)-东经,其他值无效

//*           -- bdgps_Longitude   - 经度 精度0.0001，例如：

//*           -- bdgps_ns          - 北纬南纬。返回：'N'(78)-北纬，'S'(83)-南纬,其他值无效

//*           -- bdgps_Latitude    - 纬度 精度0.0001，例如：

//*           -- bdgps_Altitude    - 海拔 精度0.0001，例如：571000,表示57.1米

//*           -- bdgps_Time   	   - 时间，例如：为1970-01-01 0:00:00年至今的UTC秒数。

//*

//* 返回值 :  成功返回ERROR_OK(==0)；失败返回(ERROR_FAIL)

//* 备注   :   无

//*--------------------------------------------------------------------------

int GetBDGPSData(int             bdgps_fd,

		char	        *bdgps_loca_state,

		char	        *bdgps_we,

		unsigned int	*bdgps_Longitude,

		char	        *bdgps_ns,

		unsigned int    *bdgps_Latitude,

		unsigned int    *bdgps_Altitude,

		unsigned int    *bdgps_Time)
{
        char newbuf[MAX_PACKET_SIZE];
        int nb;
        char *ret = NULL;
        int nQ, nN, nB, nC;                     //GPS状态,卫星数量,
        char cX, cY, cM1, cM2;                  //纬度方向,经度方向,
        float fTime, fX, fY, fP, fH, fB, fD;    //timeUTC时间,纬度,经度,精度百分比,海拔高,大地水准面高度,差分GPS数据期限
	time_t   ltime; 



while (1) {
        memset(newbuf, 0, 1024);
        nb = read(bdgps_fd, newbuf, MAX_PACKET_SIZE);
        if (nb == -1) {
            perror("read uart error");
            return -1;
        }
        if ((ret = strstr(newbuf, "$GNGGA")) != NULL) {
//	printf("%s\n",ret);
//     	strcpy(ret,"$GNGGA,000000.000,0123.456789,N,01234.123456,E,8,00,385.123,0.000,M,0,M,,*69");
        sscanf(ret,"$GNGGA,%f,%f,%c,%f,%c,%d,%02d,%f,%f,%c,%f,%c,",&fTime,&fX,&cX,&fY,&cY,&nQ,&nN,&fP,&fH,&cM1,&fB,&cM2, &fD, &nB, &nC);
//	printf("$GNGGA,%f,%f,%c,%f,%c,%d,%02d,%f,%f,%c,%f,%c\n",fTime,fX,cX,fY,cY,nQ,nN,fP,fH,cM1,fB,cM2,fD,nB,nC);
	*bdgps_loca_state = nQ;
	*bdgps_we = cY;
	*bdgps_Longitude = fY * 10000;
	*bdgps_ns = cX;
	*bdgps_Latitude = fX * 10000;
	*bdgps_Altitude = fH * 10000;
	time(&ltime); 
	*bdgps_Time = ltime;
	#ifdef GPSCONFIG
	char *iCatAge;
	char *iCatAge1;
	unsigned int a1,a2,b1,b2;
	unsigned int c;
	c = GetIniKeyInt("GPS_CONFIG","ENABLE",gps_config);
	if(c==1)
	{
	*bdgps_loca_state = 1;
	iCatAge = GetIniKeyString("GPS_CONFIG","Longitude",gps_config);
        sscanf(iCatAge,"%d.%d",&a1,&a2);
	*bdgps_Latitude = a1*10000+a2/100;
	//printf("a1 = %d a2 = %d %d\n",a1,a2,*bdgps_Latitude);
	iCatAge = GetIniKeyString("GPS_CONFIG","Latitude",gps_config);
        sscanf(iCatAge,"%d.%d",&b1,&b2);
	*bdgps_Longitude = b1*10000+b2/100;
	//printf("b1 = %d b2 = %d %d\n",b1,b2,*bdgps_Longitude);
	}
	#endif
        return 0;
        } 
        else {
                usleep(200000);
        }
}
}


//************************************************************

//*-----------------------------------------------------------

//*

//*                看门狗设备相关部分

//*

//*-----------------------------------------------------------

//************************************************************






//*------------------------------------------------------------------------------------------------

//* 函数名称:  EnableWtd

//* 功能描述:  使能看门狗设备

//* 入口参数:

//*           -- TimeOut:     - 指定看门狗的最大喂狗间隔（秒）

//*

//* 返回值：      成功返回ERROR_OK(==0)；失败返回(ERROR_INPARA/ERROR_TIMEOUT/ERROR_SYS/ERROR_NOSUPPORT/ERROR_FAIL)

//* 备注:     无

//*------------------------------------------------------------------------------------------------

int EnableWtd(int TimeOut)
{
	int    res;
	int data = 0;
#ifdef DEbug
	printf("@@@@@@@@@@@@@	EnableWtd	@@@@@@@@@@@@@@ TimeOut=%x\n",TimeOut);
#endif
	watchdog_fd=open("/dev/watchdog",O_WRONLY);
	if(watchdog_fd<0) {
		printf("open watchdog\n");
		return ERROR_FAIL;
	}
	//        printf("open watchdog success!\n");
	res = ioctl (watchdog_fd, WDIOC_GETTIMEOUT, &data);

	if (res) {
		//                printf ("\nWatchdog Timer : WDIOC_GETTIMEOUT failed");
		return ERROR_FAIL;
	}
	else {
		//                printf ("\nCurrent timeout value is : %d seconds\n", data);
	}
	data = TimeOut;
	res = ioctl (watchdog_fd, WDIOC_SETTIMEOUT, &data);
	if (res) {
		//	        printf ("\nWatchdog Timer : WDIOC_SETTIMEOUT failed");
		return ERROR_FAIL;
	}
	else {
		//	        printf ("\nNew timeout value is : %d seconds", data);
	}
	res = ioctl (watchdog_fd, WDIOC_GETTIMEOUT, &data);
	if (res) {
		//	        printf ("\nWatchdog Timer : WDIOC_GETTIMEOUT failed");
		return ERROR_FAIL;
	}
	else {
		//	        printf ("\nCurrent timeout value is : %d seconds\n", data);
	}

	/*
	   while(1)
	   {
	   FeedWtd();sleep(1);
	   }
	 */
	return ERROR_OK;
}





//*------------------------------------------------------------------------------------------------

//* 函数名称:  FeedWtd

//* 功能描述:  喂狗操作

//* 入口参数:  无

//*

//* 返回值：        成功返回ERROR_OK(==0)；失败返回(ERROR_INPARA/ERROR_TIMEOUT/ERROR_SYS/ERROR_NOSUPPORT/ERROR_FAIL)

//* 备注:      无

//*------------------------------------------------------------------------------------------------

int FeedWtd(void)
{
	//printf("@@@@@@@@@@@@@	FeedWtd	@@@@@@@@@@@@@@ \n");
	if (1 != write(watchdog_fd, "\0", 1))
	{
		return ERROR_FAIL;
	}
	return	ERROR_OK;

}





//*------------------------------------------------------------------------------------------------

//* 函数名称:  DisableWtd

//* 功能描述:  关闭看门狗

//* 入口参数:  无

//*

//* 返回值：        成功返回ERROR_OK(==0)；失败返回(ERROR_INPARA/ERROR_TIMEOUT/ERROR_SYS/ERROR_NOSUPPORT/ERROR_FAIL)

//* 备注:      无

//*------------------------------------------------------------------------------------------------

int DisableWtd(void)
{
	//printf("@@@@@@@@@@@@@ DisableWtd @@@@@@@@@@@@@@ \n");

	if (0 != close (watchdog_fd))
	{
		//	printf("Close failed\n");
		return ERROR_FAIL;
	}
	//	printf("Close succeeded\n");
	return ERROR_OK;
}









































